#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from Timer import timer
from lxml import etree


class MakeXML:
    def __init__(self, root_name, file_path):
        self.root_name = root_name
        self.root = etree.Element(root_name)
        self.etree = etree.ElementTree(self.root)
        self.file_path = file_path
        self.file_name = self.file_path.split('\\')[-1]

    def _search_xpath(self, xpath):
        """
        循环搜索目标xpath所在xml元素树中依附的父节点
        :param xpath: 目标xpath
        :return: 依附的父节点
        """
        xpath_li = xpath.split('/')
        for i in range(len(xpath_li)):
            _xpath = '/' + '/'.join(xpath_li[:-i])
            _element = self.etree.xpath(_xpath)
            if _element:
                return _xpath, _element[-1]

    @staticmethod
    def _append_element(f_xpath, f_element, attr_dict):
        """
        追加xml元素，并设置其属性
        :param f_xpath: 依赖的xml父节点的xpath
        :param f_element: 依赖的xml父节点
        :param attr_dict: load_excel产生的属性字典
        :return: 追加的xml元素
        """
        c_xpath = '/' + attr_dict['>>XPath'][2:]
        diff_xpath_list = c_xpath.replace(f_xpath, '').split('/')[1:]
        attr_dict.pop('>>XPath')
        _f_element = f_element
        for diff_xpath_sec in diff_xpath_list:
            _f_element = etree.SubElement(_f_element, diff_xpath_sec)
        c_element = _f_element
        for attr, val in attr_dict.items():
            c_element.set(attr, val)
        return c_element

    @staticmethod
    def _append_comment(f_element, cmt_dict):
        """
        追加注释
        :param f_element: 依赖的xml父节点
        :param cmt_dict: load_excel产生的注释字典
        :return: 追加的注释
        """
        cmt_string = cmt_dict['>>Commentary']
        cmt = etree.Comment(text=cmt_string)
        f_element.append(cmt)
        return cmt

    @timer()
    def make_xml(self, attr_group):
        for index, each_dict in enumerate(attr_group):
            each_dict.pop('SheetName')
            each_dict.pop('RowNum')
            if '>>XPath' in each_dict:
                _xpath = each_dict['>>XPath'][2:]
                f_xpath, f_element = self._search_xpath(_xpath)
                self._append_element(f_xpath, f_element, each_dict)
            elif '>>Commentary' in each_dict:
                _group = attr_group[index:]
                for _dic in _group:
                    if '>>XPath' in _dic:
                        _xpath = _dic['>>XPath'][2:]
                        _, f_element = self._search_xpath(_xpath)
                        self._append_comment(f_element, each_dict)
                        break

    @timer()
    def make_xml_string(self):
        xml_string = etree.tostring(self.etree, encoding='utf-8', xml_declaration=True, pretty_print=True).decode("utf-8")
        return xml_string

    @timer()
    def write_xml_file(self):
        self.etree.write(self.file_path, encoding='UTF-8', xml_declaration=True, pretty_print=True)
        with open(self.file_path, 'r', encoding='utf-8') as r:
            lines = r.readlines()
            lines[0] = '<?xml version="1.0" encoding="utf-8"?>\n'
        with open(self.file_path, 'w', encoding='utf-8') as w:
            w.writelines(lines)
        # logger.info('生成XML文档[{0}]成功'.format(self.file_path))


if __name__ == '__main__':
    import os
    from ParseExcel import ParseExcel
    objects_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'objects.xlsx')
    objects_obj = ParseExcel(objects_path)
    attr_list = objects_obj.load_excel()

    xml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'objects.xml')
    xml_obj = MakeXML('objects', xml_path)
    xml_obj.make_xml(attr_list)
    xml_doc = xml_obj.make_xml_string()
    xml_obj.write_xml_file()
